package list

type linkedNode struct {
	val        interface{}
	next, prev *linkedNode
}

type linkedList struct {
	len        int
	head, tail *linkedNode
}

func NewLinkedList() *linkedList {
	return &linkedList{0, nil, nil}
}

func (this *linkedList) Add(e interface{}) {
	node := linkedNode{e, nil, this.tail}
	this.tail = &node
	if this.head == nil {
		this.head = &node
	}
	this.len++
}

func (this *linkedList) AddAt(i int, e interface{}) {
	if i <= 0 {
		node := linkedNode{e, this.head, nil}
		this.head = &node
		if this.tail == nil {
			this.tail = &node
		}
		this.len++
		return
	}
	if i >= this.len {
		this.Add(e)
		return
	}
	p := this.head
	for c := 0; c < this.len || p != nil; c++ {
		if c == i {
			node := linkedNode{e, p.next, p.prev}
			p.next = &node
			p.next.prev = &node
			return
		}
		p = p.next
	}
}

func (this *linkedList) Capacity() int {
	return this.len
}

func (this *linkedList) Clear() {
	this.len = 0
	this.head, this.tail = nil, nil
}

func (this *linkedList) IsEmpty() bool {
	return this.len == 0
}

func (this *linkedList) Size() int {
	return this.len
}
